package com.gxa.order.service.impl;

import com.gxa.cart.pojo.CartItem;
import com.gxa.cart.service.CartService;
import com.gxa.common.exception.BusinessException;
import com.gxa.common.exception.MessageCode;
import com.gxa.common.utils.SnowFlake;
import com.gxa.goods.pojo.Sku;
import com.gxa.goods.service.SkuService;
import com.gxa.order.dto.OrderDTO;
import com.gxa.order.service.OrderService;
import com.gxa.order.eums.OrderStatusEnum;
import com.gxa.order.repository.OrderItemRepository;
import com.gxa.order.repository.OrderRepository;
import com.gxa.order.repository.OrderShippingRepository;
import com.gxa.order.repository.OrderStatusRepository;
import com.gxa.order.pojo.Order;
import com.gxa.order.pojo.OrderItem;
import com.gxa.order.pojo.OrderShipping;
import com.gxa.order.pojo.OrderStatus;
import com.gxa.user.pojo.UserShipping;
import com.gxa.user.service.UserService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;


import java.util.Date;
import java.util.List;

/**
 * Created by zxd on 2020/1/7
 **/
@org.apache.dubbo.config.annotation.Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    // 从购物车服务中找到需要添加到订单的商品信息
    @Reference
    private CartService cartService;

    // 需要用户(购买者)的信息和物流信息
    @Reference
    private UserService userService;

    // 获取商品信息
    @Reference
    private SkuService skuService;

    // 通过jpa方式操作订单业务本身
    @Autowired
    private OrderRepository orderRepository;

    // 通过jpa方式操作订单业务物流
    @Autowired
    private OrderShippingRepository orderShippingRepository;

    // 操作订单状态
    @Autowired
    private OrderStatusRepository orderStatusRepository;

    // 操作订单商品项
    @Autowired
    private OrderItemRepository orderItemRepository;


    @Override
    @GlobalTransactional  //分布式事务
    //@Transactional
    public String createOrder(Long userId, OrderDTO orderDTO)throws BusinessException {

        //生成订单id(使用雪花算法)
        String orderId= SnowFlake.nextId()+"";

        log.info("orderId is{}",orderId);

        //之所以先插入订单项是因为要计算订单总价，一次循环搞定，免得写两个循环  因为订单id是程序生成 所以顺序不影响
        //计算订单总价,减库存，分别插入订单项
        Long orderAmount=0L;
        for(String skuId:orderDTO.getSkuIds()){
            // 从数据库中找到sku商品信息
             Sku sku= skuService.findById(skuId);
            if(ObjectUtils.isEmpty(sku)){
                log.error("下单商品不存在,itemId:{}",skuId);
                throw new BusinessException(MessageCode.GOODS_STATUS);
            }
            //根据skuid查询购物项
            CartItem cartItem = cartService.queryUserCartItem(userId, sku.getId());

            if(ObjectUtils.isEmpty(cartItem)){
                log.error("下单商品不存在,itemId:{}",skuId);
                throw new BusinessException(MessageCode.GOODS_STATUS);
            }

            //扣库存   seata解决分布式事务
            skuService.updateItemStock(cartItem.getNum(),skuId);

            // 增加异常测试
            int i = 1/0;

            //购物项的数量*sku的最新价格
            // 为什么没有用购物车中sku的价格, 而要用数据库中的商品价格
            orderAmount=orderAmount+(cartItem.getNum()*sku.getPrice());

            //分别写入订单项信息
            createOrderItem(orderId, skuId, sku, cartItem);
            log.debug("decreaseStock,itemId {},num {}",sku,cartItem.getNum());

            //删除该sku在购物车的信息  TODO 方便测试暂时注释
            cartService.removeCartItem(userId,skuId);

        }


        //保存订单基本信息
        createOrder(orderDTO, orderId, orderAmount,userId);
        //保存收货地址
         createShipping(orderDTO, orderId);
        //保存订单状态
        createOrderStatus(orderId);

        return orderId;
    }

    @Override
    public Order queryOrderById(String id) {
        return orderRepository.findOrderByOrderId(id);
    }

    @Override
    public OrderStatus queryOrderStatus(String id) {
        return orderStatusRepository.findOrderStatusByOrderId(id);
    }

    @Override
    public Boolean updateOrderStatus(String orderId, Integer status)  {

        OrderStatus orderStatus = orderStatusRepository.findOrderStatusByOrderId(orderId);

        if(status<OrderStatusEnum.NO_PAYMENT.getCode()|| status>OrderStatusEnum.RATE.getCode()){
            log.error("修改状态为非法状态!");
            return false;
        }
        if(orderStatus.getStatus().equals(status)){
            log.error("修改订单状态与原状态一致，无需修改!");
           return false;
        }
        Integer result = orderStatusRepository.changeOrderState(status, orderId, orderStatus.getStatus());
        if(result>0){
         return true;
        }else{
            return false;
        }
    }



    private void createOrder(OrderDTO orderDTO, String orderId, Long orderAmount,Long userId) {
        Order order=new Order();
        order.setOrderId(orderId);
        order.setPostFee(0L);
        //TODO 包邮规则后期应该做成专门业务，此处待完善
        if(orderAmount<8000){
            //订单满80包邮,不足20元邮费
           order.setPostFee(2000L);
        }
        //实付金额
        order.setActualPay(orderAmount+order.getPostFee());

        //TODO 如果后期促销规则 实际支付可以减得
        //总金额
        order.setTotalPay(orderAmount+order.getPostFee());

        order.setBuyerMessage(orderDTO.getBuyerMessage());
        //未评价
        order.setBuyerRate(0);
        //支付方式
        order.setPaymentType(orderDTO.getPaymentType());
        order.setCreateTime(new Date());
        order.setUserId(userId);
        //发票类型
        order.setInvoiceType(orderDTO.getInvoiceType());
        order.setSourceType(orderDTO.getSourceType());
        //写入订单信息
        log.debug("crate order is {}",order);
        orderRepository.save(order);
    }

    private void createOrderStatus(String orderId) {
        //保存订单状态
        OrderStatus orderStatus=new OrderStatus();
        orderStatus.setOrderId(orderId);
        // 订单的最初状态是未支付状态
        orderStatus.setStatus(OrderStatusEnum.NO_PAYMENT.getCode());
        orderStatus.setCreateTime(new Date());
        //设置订单超时时间
        //下单时间+12小时  43200000=12小时
        orderStatus.setPaymentTime(new Date(System.currentTimeMillis()+43200000));
        log.debug("create orderStatus : {}",orderStatus);
        orderStatusRepository.save(orderStatus);
    }

    private void createOrderItem(String orderId, String skuId, Sku sku, CartItem cartItem) {
        OrderItem orderItem=new OrderItem();
        orderItem.setImage(cartItem.getImage());
        orderItem.setSkuId(skuId);
        orderItem.setOrderId(orderId);
        orderItem.setPrice(cartItem.getNum()*sku.getPrice());
        orderItem.setName(sku.getName());
        orderItem.setNum(cartItem.getNum());
        log.debug("create orderItem : {}", orderItem);
        //写入订单详情
        orderItemRepository.save(orderItem);
    }

    private void createShipping(OrderDTO orderDTO, String orderId) {
        UserShipping userShipping = userService.queryUserShippingById(orderDTO.getShippingId());
        OrderShipping orderShipping=new OrderShipping();
        orderShipping.setOrderId(orderId);
        orderShipping.setUpdated(new Date());
        orderShipping.setReceiverAddress(userShipping.getReceiverAddress());
        orderShipping.setReceiverCity(userShipping.getReceiverCity());
        orderShipping.setReceiverName(userShipping.getReceiverName());
        orderShipping.setReceiverPhone(userShipping.getReceiverPhone());
        orderShipping.setReceiverProvince(userShipping.getReceiverProvince());
        orderShipping.setReceiverTown(userShipping.getReceiverTown());
        log.debug("create orderShipping : {}",orderShipping);
        orderShippingRepository.save(orderShipping);
    }

    //分布式事务  需要加库存
    @GlobalTransactional
    @Override
    public void cancelOrder(String orderId) {

        //1.设置订单状态为交易关闭
        updateOrderStatus(orderId,OrderStatusEnum.NO_PAYMENT.getCode());

        //2.查询该订单所有订单项
        List<OrderItem> orderItemList = orderItemRepository.findOrderItemByOrderId(orderId);

        //3.遍历订单项加回库存
        orderItemList.forEach(orderItem -> {
            skuService.addItemStock(orderItem.getNum(),orderItem.getSkuId());
        });

    }


}
